package io.gitee.vexlife.snake.ui;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import io.gitee.vexlife.snake.GameController;
import io.gitee.vexlife.snake.IAgent;
import io.gitee.vexlife.snake.basic.FoodShape;

public class SettingsDialog extends JDialog {

	private GameController originalState;
	private JColorChooser colorPicker;

	/**
	 * 提供一个默认的游戏设置对话框。
	 * 
	 * @param originalState 配置选项收集前的GameController对象
	 */
	public SettingsDialog(GameController originalState) {
		super();
		this.setTitle("游戏设置");
		this.originalState = originalState;
		this.colorPicker = new JColorChooser();

		BoxLayout verticalLayout = new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS);
		this.setLayout(verticalLayout);

		JLabel lScreenSize = new JLabel("游戏屏幕大小");
		JLabel lScreenWidth = new JLabel("宽");
		JLabel lScreenHeight = new JLabel("高");
		JLabel lInitialSnakeLength = new JLabel("初始蛇身长度");
		JLabel lGameInterval = new JLabel("蛇移动的速度（毫秒/步）");
		JLabel lUnitSize = new JLabel("游戏屏幕单元大小");
		JLabel lFoodStroke = new JLabel("食物大小");
		JLabel lFoodShape = new JLabel("食物形状");
		JLabel lSnakeStroke = new JLabel("蛇宽");
		JLabel lFoodColor = new JLabel("食物颜色");
		JLabel lSnakeColor = new JLabel("蛇颜色");
		JLabel lBackgroundColor = new JLabel("游戏屏幕颜色");

		JPanel contents = new JPanel();
		contents.setLayout(new GridBagLayout());
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.fill = GridBagConstraints.BOTH;
		constraints.ipadx = 10;
		constraints.ipady = 3;

		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.gridwidth = 1;
		constraints.gridheight = 2;
		contents.add(lScreenSize, constraints);
		constraints.gridy = 2;
		constraints.gridheight = 1;
		contents.add(lInitialSnakeLength, constraints);
		constraints.gridy++;
		contents.add(lGameInterval, constraints);
		constraints.gridy++;
		contents.add(lUnitSize, constraints);
		constraints.gridy++;
		contents.add(lSnakeStroke, constraints);
		constraints.gridy++;
		contents.add(lFoodShape, constraints);
		constraints.gridy++;
		contents.add(lFoodStroke, constraints);
		constraints.gridy++;
		contents.add(lSnakeColor, constraints);
		constraints.gridy++;
		contents.add(lFoodColor, constraints);
		constraints.gridy++;
		contents.add(lBackgroundColor, constraints);

		constraints.gridx = 1;
		constraints.gridy = 0;
		contents.add(lScreenWidth, constraints);
		constraints.gridx = 1;
		constraints.gridy = 1;
		contents.add(lScreenHeight, constraints);
		JSpinner sScreenWidth = new JSpinner(new SpinnerNumberModel(originalState.getWidth(), 2, null, 1));
		constraints.gridx = 2;
		constraints.gridy = 0;
		contents.add(sScreenWidth, constraints);
		JSpinner sScreenHeight = new JSpinner(new SpinnerNumberModel(originalState.getHeight(), 2, null, 1));
		constraints.gridy++;
		contents.add(sScreenHeight, constraints);
		JSpinner sInitialSnakeLength = new JSpinner(
				new SpinnerNumberModel(originalState.getInitialSnakeLength(), 1, originalState.getWidth() - 1, 1));
		constraints.gridy++;
		constraints.gridx = 1;
		constraints.gridwidth = 2;
		contents.add(sInitialSnakeLength, constraints);
		sScreenWidth.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				if ((int) sInitialSnakeLength.getValue() >= (int) sScreenWidth.getValue())
					sInitialSnakeLength.setValue((int) sScreenWidth.getValue() - 1);
				((SpinnerNumberModel) sInitialSnakeLength.getModel())
						.setMaximum((Comparable<?>) ((int) sScreenWidth.getValue() - 1));
			}

		});
		JSpinner sGameInterval = new JSpinner(new SpinnerNumberModel(originalState.getGameInterval(), 10, null, 10));
		constraints.gridy++;
		contents.add(sGameInterval, constraints);
		JSpinner sUnitSize = new JSpinner(new SpinnerNumberModel(originalState.UNIT_SIZE, 1, null, 1));
		constraints.gridy++;
		contents.add(sUnitSize, constraints);
		JSpinner sSnakeStroke = new JSpinner(
				new SpinnerNumberModel(originalState.SNAKE_STROKE, 1, originalState.UNIT_SIZE, 1));
		constraints.gridy++;
		contents.add(sSnakeStroke, constraints);
		JComboBox cbFoodShape = new JComboBox(FoodShape.values());
		cbFoodShape.setSelectedItem(originalState.shape_Food);
		constraints.gridy++;
		contents.add(cbFoodShape, constraints);
		JSpinner sFoodStroke = new JSpinner(
				new SpinnerNumberModel(originalState.FOOD_STROKE, 1, originalState.UNIT_SIZE, 1));
		constraints.gridy++;
		contents.add(sFoodStroke, constraints);
		sUnitSize.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				if ((int) sSnakeStroke.getValue() > (int) sUnitSize.getValue())
					sSnakeStroke.setValue(sUnitSize.getValue());
				((SpinnerNumberModel) sSnakeStroke.getModel()).setMaximum((Comparable<?>) (sUnitSize.getValue()));
				if ((int) sFoodStroke.getValue() > (int) sUnitSize.getValue())
					sFoodStroke.setValue(sUnitSize.getValue());
				((SpinnerNumberModel) sFoodStroke.getModel()).setMaximum((Comparable<?>) (sUnitSize.getValue()));
			}

		});
		JLabel cSnakeColor = new JLabel();
		cSnakeColor.setBackground(originalState.color_Snake);
		cSnakeColor.setOpaque(true);
		constraints.gridy++;
		contents.add(cSnakeColor, constraints);
		cSnakeColor.addMouseListener(new MouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {
				SettingsDialog.this.inquireColor("选择蛇颜色", cSnakeColor);
			}

			@Override
			public void mousePressed(MouseEvent e) {

			}

			@Override
			public void mouseReleased(MouseEvent e) {

			}

			@Override
			public void mouseEntered(MouseEvent e) {

			}

			@Override
			public void mouseExited(MouseEvent e) {

			}

		});
		JLabel cFoodColor = new JLabel();
		cFoodColor.setBackground(originalState.color_Food);
		cFoodColor.setOpaque(true);
		constraints.gridy++;
		contents.add(cFoodColor, constraints);
		cFoodColor.addMouseListener(new MouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {
				SettingsDialog.this.inquireColor("选择食物颜色", cFoodColor);
			}

			@Override
			public void mousePressed(MouseEvent e) {

			}

			@Override
			public void mouseReleased(MouseEvent e) {

			}

			@Override
			public void mouseEntered(MouseEvent e) {

			}

			@Override
			public void mouseExited(MouseEvent e) {

			}

		});
		JLabel cBackgroundColor = new JLabel();
		cBackgroundColor.setBackground(originalState.color_Background);
		cBackgroundColor.setOpaque(true);
		constraints.gridy++;
		contents.add(cBackgroundColor, constraints);
		cBackgroundColor.addMouseListener(new MouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {
				SettingsDialog.this.inquireColor("选择游戏屏幕颜色", cBackgroundColor);
			}

			@Override
			public void mousePressed(MouseEvent e) {

			}

			@Override
			public void mouseReleased(MouseEvent e) {

			}

			@Override
			public void mouseEntered(MouseEvent e) {

			}

			@Override
			public void mouseExited(MouseEvent e) {

			}

		});

		JButton ok = new JButton("确定");
		JButton cancel = new JButton("取消");
		ok.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				SettingsDialog.this.originalState.setOver(true);
				SettingsDialog.this.originalState.getMainFrame().dispose();
				int selectedIndex = SettingsDialog.this.originalState.getAgents()
						.indexOf(SettingsDialog.this.originalState.getSelectedAgent());
				SettingsDialog.this.originalState = new GameController(SettingsDialog.this,
						(int) sScreenWidth.getValue(), (int) sScreenHeight.getValue(), (int) sGameInterval.getValue(),
						(int) sInitialSnakeLength.getValue(), (int) sUnitSize.getValue(), (int) sSnakeStroke.getValue(),
						(int) sFoodStroke.getValue(), cSnakeColor.getBackground(), cFoodColor.getBackground(),
						cBackgroundColor.getBackground(), (FoodShape) cbFoodShape.getSelectedItem(),
						SettingsDialog.this.originalState.getAgents().toArray(new IAgent[0]));
				SettingsDialog.this.originalState.selectAgent(selectedIndex);
				SettingsDialog.this.originalState.startGame();
				SettingsDialog.this.dispose();
			}

		});
		cancel.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				SettingsDialog.this.dispose();
			}

		});
		JPanel op = new JPanel(new FlowLayout(FlowLayout.RIGHT));
		op.add(ok);
		op.add(cancel);

		this.add(contents);
		this.add(op);

		this.pack();
	}
	
	public void inquireColor(String title, JLabel target) throws HeadlessException {

		this.colorPicker.setPreviewPanel(new JPanel());
		this.colorPicker.setColor(target.getBackground());

		JDialog dialog = JColorChooser.createDialog(this, title, true, this.colorPicker, new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				target.setBackground(colorPicker.getColor());
			}

		}, null);

		dialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		dialog.setVisible(true);
	}

}
